home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_pcdp / ada / ra.ada < prev    next >
Text File  |  1996-01-30  |  4KB  |  145 lines

  1. with Semaphore_Package; use Semaphore_Package;
  2. with Text_IO; use Text_IO;
  3. procedure RA is
  4.  
  5.   type Node_Count is range 0..4;
  6.   subtype Node_ID is Node_Count range 1..Node_Count'Last;
  7.  
  8.   task type Nodes is
  9.     entry Init(ID: Node_ID);
  10.     entry Request_Message(Num: Integer; ID: Node_ID);
  11.     entry Reply_Message;
  12.   end Nodes;
  13.  
  14.   Node: array(Node_ID) of Nodes;
  15.  
  16.   task body Nodes is
  17.  
  18.     Number:      Integer          := 0;
  19.     High_Number: Integer          := 0;
  20.     Requesting:  Boolean          := False;
  21.     Reply_Count: Node_Count       := 0;
  22.     S:           Binary_Semaphore := Init(1);
  23.     Wake_Up:     Binary_Semaphore := Init(0);
  24.     Deferred:    array(Node_ID) of Boolean := (others => False);
  25.     I:           Node_ID;
  26.     Received_Number: Integer;
  27.     Received_ID:     Node_ID;
  28.  
  29.     pragma Volatile(Number);
  30.     pragma Volatile(High_Number);
  31.     pragma Volatile(Requesting);
  32.     pragma Volatile(Reply_Count);
  33.     pragma Volatile(Deferred);
  34.  
  35.     task Main_Process is
  36.       entry Init;
  37.     end Main_Process;
  38.  
  39.     task body Main_Process is
  40.  
  41.       procedure Choose_Number is
  42.       begin
  43.         Wait(S);
  44.         Requesting := True;
  45.         Number := High_Number + 1;
  46.         Signal(S);
  47.       end Choose_Number;
  48.  
  49.       procedure Send_Request is
  50.         begin
  51.         Reply_Count := 0;
  52.         for J in Node_ID loop
  53.           if J /= I then
  54.             Node(J).Request_Message(Number, I);
  55.             Put_Line(" " & Node_ID'Image(I) & " sending request to " &
  56.                 Node_ID'Image(J) & " with number " &
  57.                 Integer'Image(Number));
  58.           end if;
  59.         end loop;
  60.       end Send_Request;
  61.  
  62.       procedure Reply_to_Deferred_Nodes is
  63.       begin
  64.         Wait(S);
  65.         Requesting := False;
  66.         Signal(S);
  67.         for J in Node_ID loop
  68.           if Deferred(J) then
  69.             Put_Line(" " & Node_ID'Image(I) & " sending deferred reply to " &
  70.                      Node_ID'Image(J));
  71.             Deferred(J) := False;
  72.             Node(J).Reply_Message;
  73.           end if;
  74.         end loop;
  75.       end Reply_to_Deferred_Nodes;
  76.  
  77.     begin
  78.       accept Init;
  79.       for M in 1..3 loop
  80.         Put_Line(" " & Node_ID'Image(I) & " non-critical section" );
  81.         Choose_Number;
  82.         Send_Request;
  83.         Wait(Wake_Up);
  84.         Put_Line(" " & Node_ID'Image(I) & " critical section");
  85.         Reply_to_Deferred_Nodes;
  86.         Put_Line(" " & Node_ID'Image(I) & " replied to deferred nodes");
  87.       end loop;
  88.     end Main_Process;
  89.  
  90.     procedure Received_Request is
  91.       Decide_to_Defer: Boolean;
  92.     begin
  93.         Put_Line(" " & Node_ID'Image(I) & " with number " &
  94.            Integer'Image(Number) & " received request from " &
  95.            Node_ID'Image(Received_ID) & " with number " &
  96.            Integer'Image(Received_Number));
  97.         if Received_Number > High_Number then
  98.           High_Number := Received_Number;
  99.         end if;
  100.         Wait(S);
  101.         Decide_to_Defer := Requesting and
  102.              ( Number < Received_Number or
  103.               (Number = Received_Number and
  104.                I < Received_ID) );
  105.         if Decide_to_Defer then
  106.           Deferred(Received_ID) := True;
  107.           Put_Line(" " & Node_ID'Image(I) & " decides to defer " &
  108.                    Node_ID'Image(Received_ID));
  109.           Signal(S);
  110.         else
  111.           Put_Line(" " & Node_ID'Image(I) & " sending reply to " &
  112.                 Node_ID'Image(Received_ID));
  113.           Signal(S);
  114.           Node(Received_ID).Reply_Message;
  115.         end if;
  116.     end Received_Request;
  117.  
  118.   begin
  119.     accept Init(ID: Node_ID) do
  120.       I := ID;
  121.       Main_Process.Init;
  122.     end Init;
  123.     loop
  124.       select
  125.         accept Request_Message(Num: Integer; ID: Node_ID) do
  126.           Received_Number := Num;
  127.           Received_ID     := ID;
  128.         end Request_Message;
  129.         Received_Request;
  130.       or
  131.         accept Reply_Message;
  132.         Reply_Count := Reply_Count + 1;
  133.         if Reply_Count = Node_ID'Last - 1 then Signal(Wake_Up); end if;
  134.       or
  135.         terminate;
  136.       end select;
  137.     end loop;
  138.   end Nodes;
  139.  
  140. begin
  141.   for J in Node_ID loop
  142.     Node(J).Init(J);
  143.   end loop;
  144. end RA;
  145.